home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / MNetsrc.hqx / Mac TCP_IP Source v.33 / mac_tools.c < prev    next >
Text File  |  1989-04-06  |  38KB  |  1,353 lines

  1.  
  2. #include "mac_tools.h"            /* define compiler in here    */
  3.  
  4.     #include <MemoryMgr.h>
  5.     #include <Quickdraw.h>
  6.     #include <EventMgr.h>
  7.     #include <ResourceMgr.h>
  8.     #include <TextEdit.h>
  9.     #include <DialogMgr.h>
  10.     #include <strings.h>
  11.     #include <stdio.h>
  12.     #include <PackageMgr.h>
  13.     #include <ToolboxUtil.h>
  14.     #include <StdFilePkg.h>
  15.     #include <pascal.h>
  16.     #include "global.h"
  17.     
  18.     #define  ZZ    
  19.  
  20. #define TRUE (-1)        /* local definitions             */
  21. #define FALSE 0
  22. #define maxsruns 50        /* procedure table size            */
  23. #define MESSN 30        /* array size for message dialog items    */
  24. #define QUESN 40        /* array size for prompt dialog items    */
  25. #define ROM85   0x28E        /* new rom stuff             */
  26. #define NEWROM  0x7FFF
  27. #define inzoomout 8
  28. #define inzoomin  7
  29. #define zoomproc  8
  30.  
  31. typedef struct {            /* structure for an Item    */
  32.     char        itemname[40];
  33.     int        itemno;        /* Item number within menu     */
  34.     int        menuId;        /* menu id            */
  35.     MenuHandle    menuhand;    /* Item's menu's Handle                 */
  36.     ProcPtr        menurun;    /* procedure to run         */
  37.     Ptr        next;        /* pointer to the next Item     */
  38. } itemdatum;
  39.  
  40. typedef struct {            /* structure for a menu     */
  41.     char         menuname[20];    /* to allow reference by name     */
  42.     int         menuId;        /* menu id             */
  43.     MenuHandle    menuhand;    /* menu Handle to reference menu*/
  44.     itemdatum    **itemlist;    /* pointer to the list of items */
  45.     Ptr         next;        /* pointer to the next menu     */
  46. } menudatum;
  47.  
  48. typedef struct {            /* structure for a window     */
  49.     char        windname[80];    /* window's name and reference     */
  50.     WindowPtr    wptr;        /* window's pointer reference     */
  51.     ProcPtr    wact;            /* the activate procedure     */
  52.     ProcPtr    wdeact;            /* the deactivate procedure     */
  53.     ProcPtr    wupdate;        /* the update procedure     */
  54.     ProcPtr    wcontent;        /* the content procedure     */
  55.     Ptr        next;        /* pointer to the next window     */
  56. } winddatum;
  57.  
  58.   pascal Boolean     *TrackBox() = 0xA83B; 
  59.   pascal void         *ZoomWindow() = 0xA83A;
  60.  
  61. WindowPtr windowpoint();
  62. extern struct SysEnvRec *sysenvn;
  63.  
  64. /* Local variables */
  65.  
  66. static menudatum **simplemenus;        /* Handle to menu data         */
  67. static char     accname[80];        /* desk accessory name to open     */
  68. static Rect     dragrect, sizerect;    /* limits for moving windows     */
  69. static Rect     swholescreen;
  70. static winddatum **simplewinds;        /* Handle to window data     */
  71. static int    firstwind;        /* if no windows have been made    */
  72. static ProcPtr     simpleruns[maxsruns];    /* list of procedures to run     */
  73. static WindowPtr debugw;        /* window pointer for debugging */
  74. static int    snewrom;
  75. static int    getlinecaps = FALSE;
  76. static int    MFenable = 0;
  77. static long    MFticks = 0L;
  78.  
  79. /************************************************************************/
  80. /* GLOBAL USER MODIFIABLE VARIABLES                     */
  81. /* These are variables that you can declare extern so that you can use    */
  82. /* them to change the SimpleTools defaults                */
  83. /************************************************************************/
  84.  
  85. /* wprocid = type of window to Create on next window() call        */
  86.  
  87. int         wprocid = documentProc;    
  88.  
  89. /* dogoaway = is the next created window to have a go-away box        */
  90.  
  91. int         dogoaway = TRUE;    
  92.  
  93. /* keydownproc = the procedure to be called when keyDown is detected    */
  94. /* autokeyproc = the procedure to be called when autoKey is detected    */
  95. /* BOTH OF THESE ARE PASSED THE EVENTRECORD SO THE KEY CAN BE FOUND    */
  96.  
  97. ProcPtr     keydownproc,
  98.           autokeyproc;         
  99.         
  100. /* applestring = a string containing the Apple for menu reference    */
  101.  
  102. char         applestring[2] 
  103.           = {'\024', '\0'};     
  104.  
  105. /* windmenu = does the next window created get a choice under the
  106.               window menu (so a closed window can be brought back)    */
  107.               
  108. int         windmenu = TRUE;    
  109.  
  110. /* sizeredraw = is the window's content area erased and made
  111.                 updateable upon being resized                */
  112.                 
  113. int        sizeredraw = FALSE;    
  114.  
  115.  
  116. /******************************************************************/
  117. /* Dialog lists.  These were calculated by using the new resource */
  118. /* editor to make a template for a dialog and then using fedit to */
  119. /* list the hex listing of the Item list for the dialog.      */
  120. /******************************************************************/
  121.  
  122. int messd[MESSN] = {2,0,0,0x38,0xf1,0x4c,0x12d,0x402,0x4f4b,0,0,5,5,
  123.         0x36,0x12d,0x800,0,0,0x38,0xac,0x4c,0xe8,0x406,
  124.         0x4361,0x6e63,0x656c};
  125. int quesd[QUESN] = {3,0,0,0x21,0xf0,0x35,0x12c,0x402,0x4f4b,0,0,8,8,
  126.         0x28,0xe8,0x800,0,0,0x2b,8,0x4b,0xe8,0x1000,0,0,
  127.         8,0xf0,0x1c,0x12c,0x406,0x4361,0x6e63,0x656c};
  128.         
  129.         
  130. /* Local procedure */
  131.  
  132. static
  133. stnop()                /* a no op procedure for defaults     */
  134. {
  135. }
  136.  
  137. #define ptoc PtoCstr
  138. #define ctop CtoPstr
  139.  
  140. /* Given a menu name, find our data structure for it.  Return a Handle
  141.    to this structure.  This is a local procedure for SimpleTools use.
  142. */
  143.  
  144. /* local procedure */
  145.  
  146. static
  147. menudatum **getourmenuhandle (name)
  148. char *name;                /* name of menu bar menu */
  149. {
  150.     menudatum **here, **temp;    /* hand to menu structure*/
  151.     here = simplemenus;
  152.  
  153.     /* find the menu name or the end of out menu list */
  154.     HLock (here);
  155.     while (strcmp(name,(**here).menuname) && (**here).next )  {
  156.         temp = here;
  157.         here = (menudatum **)(**here).next;
  158.         HUnlock (temp);
  159.         HLock (here);
  160.     }
  161.         
  162.     /* see if we found it or just the end of the list */
  163.     if (!strcmp(name,(**here).menuname)) {
  164.         HUnlock (here);
  165.         return (here);
  166.     } else {
  167.         HUnlock (here);
  168.         return ((menudatum **)0L);        
  169.     }
  170. }
  171.  
  172. /* This takes a Handle to our personal Item record and either a 
  173.    procedure name or a modifier code.  If it got a procedure name,
  174.    it sets it to the Item's procedure to run when the Item is chosen.
  175.    If it got a modifier code, it changes the state of the menu's Item
  176.    to checked, unchecked, enabled, or disabled.  It especially keeps 
  177.    track of the standard Edit menu items so we can restore them after
  178.    a desk accessory is finished.
  179. */
  180.  
  181. /* Local procedure */
  182.  
  183. static
  184. setitems ( items, routine)    /* set a menu Item's routine or display */
  185. itemdatum    **items;    /* if items is neg, then whole menu     */
  186. ProcPtr    routine;
  187. {
  188.     int            inumber;
  189.     MenuHandle        mhand;
  190.     
  191.     /* check to see if a procedure pointer was given to us */
  192.     if ( (((long)items)>0L) && (routine > (ProcPtr)0x1000L)) {  
  193.                         /* good procedure value */
  194.         (**items).menurun = routine;
  195.         return;
  196.     }
  197.     
  198.     /* Calculate which Item number we are going to modify */
  199.     if ( (long)items < 0L) {        /* the whole menu     */
  200.         mhand = (MenuHandle) (0L - (long)items);
  201.         inumber = 0;
  202.     } else {                /* just one Item     */
  203.         mhand = (**items).menuhand;
  204.         inumber = (**items).itemno;
  205.     }
  206.  
  207.     /* If a NULL procedure pointer, then set to a no_op routine */
  208.     if ( (inumber > 0) && ((**items).menurun == (ProcPtr)0L) )
  209.         (**items).menurun = stnop;
  210.  
  211.     /* Now change the state of a menu Item */
  212.     switch ((int)routine) {
  213.         case itemdisable: 
  214.             DisableItem(mhand,inumber); break;
  215.         case itemenable:
  216.             EnableItem(mhand, inumber); break;
  217.         case itemcheck:
  218.             CheckItem(mhand, inumber, TRUE); break;
  219.         case itemuncheck:
  220.             CheckItem(mhand, inumber, FALSE); break;
  221.     }
  222.     if (inumber == 0) DrawMenuBar();  /* if main menu was changed     */
  223.     
  224. }
  225.  
  226. /* This routine is called by the simpletools() initial routine.  It gets
  227.    the pointer list of menus started, loads the desk accessories into
  228.    the Apple menu, and loads up some standard menu entries.  The reason
  229.    menu File has a New entry, and none others, is because as this code
  230.    currently stands, a menu must have at least one Item.  And since we
  231.    want File before Edit, I had to make an entry.  The most commonly used
  232.    Item under File is Quit.  But we like quit to be at the end of the list.
  233.    So, since New is usually always first when it is used, that the one
  234.    chosen to start File.  
  235. */
  236.  
  237. /* Local procedure */
  238.  
  239. static
  240. initsmenus(about)            /* init simpletools' menus */
  241. char *about;
  242. {
  243.     itemdatum **items;
  244.  
  245.     simplemenus = (menudatum **) NewHandle ( (long)sizeof(menudatum));
  246.     HLock (simplemenus);
  247.  
  248.     strcpy ( (**simplemenus).menuname, applestring);
  249.     (**simplemenus).menuId = 1;
  250.     (**simplemenus).next = (Ptr) 0L;
  251.     ctop ((**simplemenus).menuname);
  252.     (**simplemenus).menuhand = NewMenu (1, (**simplemenus).menuname);
  253.     ptoc ((**simplemenus).menuname);
  254.     HUnlock ((**simplemenus).menuhand);
  255.  
  256.     (**simplemenus).itemlist = (itemdatum **)NewHandle ( 
  257.             (long)sizeof(itemdatum));
  258.     items = (itemdatum **) (**simplemenus).itemlist;
  259.     HLock (items);
  260.  
  261.     strcpy ((**items).itemname, about);
  262.     (**items).itemno = 1;
  263.     (**items).menuId = 1;
  264.     (**items).menuhand = (**simplemenus).menuhand;
  265.     (**items).menurun = stnop;
  266.     (**items).next = 0L;
  267.     HUnlock (items);
  268.  
  269.     ctop (about);
  270.     AppendMenu ((**simplemenus).menuhand, about);
  271.     ptoc (about);
  272.     menu (applestring, about, (ProcPtr)itemenable);
  273.     menu (applestring, "Help" , (ProcPtr)itemenable);
  274.     menu (applestring, "-", (ProcPtr) itemdisable);
  275.       AddResMenu ((**simplemenus).menuhand, 'DRVR');
  276.     InsertMenu ((**simplemenus).menuhand, 0);
  277.     HUnlock (simplemenus);
  278.  
  279.     menu ("File", "New", (ProcPtr)itemdisable);
  280.     menu ("Edit", "Undo", (ProcPtr)stnop);
  281.     menu ("Edit", "-", (ProcPtr)itemdisable);
  282.     menu ("Edit", "Cut/X", (ProcPtr)stnop);
  283.     menu ("Edit", "Copy/C", (ProcPtr)stnop);
  284.     menu ("Edit", "Paste/V", (ProcPtr)stnop);
  285.     menu ("Edit", "Clear", (ProcPtr)stnop);
  286. }
  287.  
  288. /* Local procedure */
  289.  
  290. static
  291. gottrans ()
  292. {
  293.     char prog[80];
  294.     char *argv[3];
  295.     if (getfile("APPL",prog)) {
  296.         argv[1] = NULL;
  297.         execv(prog,argv);
  298.     }
  299. }
  300.  
  301. /* Local procedure */
  302.  
  303. static
  304. gotquit ()
  305. {
  306.     exit(0);
  307. }
  308.  
  309. /* This routine is for the Windows menu Item.  The Windows menu is
  310.    set up when new windows are added.  It is used to bring forward and
  311.    bring into view windows that may be under other windows or have been
  312.    sent hiding by a click on their close box.
  313. */
  314.  
  315. /* Local procedure */
  316.  
  317. static
  318. showawindow(name)            /* show the named window    */
  319. char *name;
  320. {
  321.     WindowPtr foo;
  322.     foo = windowpoint(name);    /* get its window pointer    */
  323.     if ( foo ) {
  324.         ShowWindow(foo);    /* show it on the screen    */
  325.         SetPort (foo);        /* set further output to it */
  326.         if ( foo != FrontWindow())    /* if it isn't active,    */
  327.             SelectWindow (foo);    /* activate it         */
  328.     }
  329. }
  330.  
  331. /* Local procedure */
  332.  
  333. static
  334. winddatum **wdatum(windpt)        /* return Handle to window data */
  335. WindowPtr windpt;
  336. {
  337.     winddatum **wind, **temp;
  338.  
  339.     if (firstwind) return ((winddatum **) 0L);
  340.     wind = simplewinds;
  341.     HLock (wind);
  342.  
  343.     while ( ((**wind).wptr != windpt) && (**wind).next) {
  344.         temp = wind;
  345.         wind = (winddatum **) (**wind).next;
  346.         HUnlock (temp);
  347.         HLock (wind);
  348.     }
  349.  
  350.     if ( (**wind).wptr == windpt) {
  351.         HUnlock (wind);
  352.         return (wind);
  353.     } else {
  354.         HUnlock (wind);
  355.         return ((winddatum **) 0L);    /* zero if not found */
  356.     }
  357. }
  358.   
  359. /* Local procedure */
  360.  
  361. static
  362. runruns(event)            /* run all the installed run procedures    */
  363. EventRecord *event;        /* returns number of routines run     */
  364. {
  365.     int i=0;
  366.     WindowPtr saveport;
  367.     GetPort (&saveport);
  368.     while ( simpleruns[i] )
  369.         (*(simpleruns[i++])) (event);
  370.     SetPort (saveport);
  371.     return(i);
  372. }
  373.  
  374. /* Local procedure */
  375.  
  376. static
  377. stdialog( question, answer, type)  /* a general dialog displayer     */
  378. char *question;
  379. char *answer;
  380. int  type;            /* type:  1=prompt, 2=message         */
  381. {
  382.     DialogPtr dialog;    /* dialog reference             */
  383.     Handle Item, items;    /* handles for the dialog items     */
  384.     Rect screen, box;    /* rectangles for dialog/items         */
  385.     int dtype, hit, canc;    /* Item type and which was hit         */
  386.     char tempanswer[256];    /* address where answer is         */
  387.  
  388.     items = NewHandle (512L);/* get memory for items list         */
  389.     HLock (items);        /* lock it down             */
  390.     if (type == 1)
  391.         BlockMove (quesd, *items, (long) QUESN * 2L); 
  392.     else
  393.         BlockMove (messd, *items, (long) MESSN * 2L);
  394.     SetRect (&screen, 103, 50, 409, 137);        
  395.         
  396.     dialog = NewDialog (0L, &screen, "", 0, dBoxProc, -1L, 0, 0L, items);
  397.     GetDItem (dialog, 2, &dtype, &Item, &box);
  398.     ctop (question);    
  399.     SetIText (Item, question);        /* set Item#2 text     */
  400.     ptoc (question);
  401.     if (type == 1) {            /* set default answer    */
  402.         GetDItem (dialog, 3, &dtype, &Item, &box);
  403.         ptoc (answer);
  404.         SetIText (Item, answer);
  405.         ctop (answer);
  406.         canc = 4;
  407.     } else
  408.         canc = 3;
  409.     ShowWindow (dialog);            /* display the dialog    */
  410.     do {
  411.         ModalDialog (0L, &hit);        /* process the dialog    */
  412.     } while ( (hit != 1) & (hit != canc) );
  413.     if (type == 1) {
  414.         GetDItem (dialog, 3, &dtype, &Item, &box);
  415.         HLock (Item);
  416.         GetIText (Item, tempanswer);    /* get Item#3 text     */
  417.         ptoc (tempanswer);
  418.         strcpy (answer, tempanswer);    /* make a copy of it     */
  419.         HUnlock (Item);
  420.     }
  421.     HUnlock(items);                /* unlock items memory    */
  422.     HPurge(items);                /* purge it         */
  423.     DisposDialog (dialog);            /* get rid of dialog    */
  424.     return ( hit==1 );            /* return true if ok    */
  425. }  
  426.   
  427. /* Local procedures */
  428.  
  429. static
  430. docommand (which, thisevent)
  431. long which;
  432. EventRecord *thisevent;
  433. {
  434.     int themenu, theitem;
  435.     long size;
  436.     char *cpoint;
  437.     GrafPtr tempport;
  438.     menudatum **here, **temp;
  439.     itemdatum **items, **tempitems;
  440.     char **myreshandle;
  441.     Handle myhandle;
  442.   
  443.     themenu = HiWord (which);
  444.     theitem = LoWord (which);
  445.     if ((themenu == 1) && (theitem >= 3)) {
  446.   
  447.         /* start up a desk accessory */
  448.         HLock (simplemenus);
  449.         GetItem ((**simplemenus).menuhand, theitem, accname);
  450.         SetResLoad (FALSE);
  451.           myreshandle = GetNamedResource ('DRVR', accname);
  452.         SetResLoad (TRUE);
  453.         size = SizeResource (myreshandle);
  454.         myhandle = NewHandle ( size + 3072L);
  455.         if (myhandle == 0L) 
  456.             message ("Not enough memory to do that.");
  457.         else {
  458.             DisposHandle (myhandle);
  459.             GetPort (&tempport);
  460.             OpenDeskAcc(accname);
  461.             SetPort (tempport);
  462.         }
  463.         HUnlock (simplemenus);
  464.         return;
  465.     }
  466.     if (themenu ==3) {
  467.         /* do any system edits */
  468.         if (SystemEdit(theitem -1))  return;
  469.     }
  470.   
  471.     /* now we run an installed menu procedure */
  472.     here = simplemenus;
  473.     HLock (here);
  474.   
  475.     /* find out menu structure given the menu id */
  476.     while ( ((**here).menuId != themenu) && (**here).next) {
  477.         temp = here;
  478.         here = (menudatum **)(**here).next;
  479.         HUnlock (temp);
  480.         HLock (here);
  481.     }
  482.   
  483.     if ((**here).menuId == themenu) {
  484.   
  485.         /* now find the Item structure */
  486.         items = (**here).itemlist;
  487.         HUnlock (here);
  488.         HLock (items);
  489.  
  490.         while ( ((**items).itemno != theitem) && (**items).next) {
  491.             tempitems = items;
  492.             items = (itemdatum **)(**items).next;
  493.             HUnlock (tempitems);
  494.             HLock (items);
  495.         }
  496.   
  497.         /* prepare to give the Item name to the procedure */
  498.         cpoint = (**items).itemname;
  499.         if ((**items).itemno == theitem) 
  500.         /* if we found the Item, call its procedure */
  501.             (*((**items).menurun))(cpoint,thisevent) ;
  502.         HUnlock (items);
  503.     }
  504. }
  505.  
  506. /* Local procedure */
  507.  
  508. static
  509. domousedown(thisevent)        /* respond to mouse down events */
  510. EventRecord *thisevent;        /* passed the event record */
  511. {
  512.     WindowPtr whichwindow;
  513.     int code, x, y;
  514.     char *cpoint;
  515.     menudatum **omhand;
  516.     winddatum **thewdatum;
  517.     long newplace;
  518.     Point temp;
  519.     GrafPtr saveport;
  520.  
  521.     code = FindWindow(ZZ(thisevent->where), &whichwindow);
  522.     switch (code) {
  523.         case inMenuBar:
  524.         docommand(MenuSelect(ZZ(thisevent->where)),thisevent);
  525.         break;
  526.         case inSysWindow:
  527.         SystemClick(thisevent, whichwindow); break;
  528.         case inDrag:
  529.         DragWindow(whichwindow, ZZ(thisevent->where),
  530.             &dragrect); break;
  531.         case inGrow:
  532.         newplace= GrowWindow(whichwindow, ZZ(thisevent->where),
  533.             &sizerect);
  534.         SizeWindow(whichwindow, LoWord(newplace), 
  535.         HiWord(newplace), TRUE);
  536.         if (sizeredraw) {
  537.             GetPort (&saveport);
  538.             SetPort (whichwindow);
  539.             EraseRect (&swholescreen);
  540.             InvalRect (&swholescreen);
  541.             SetPort (saveport);
  542.         }
  543.         break;
  544.         case inGoAway:
  545.         if ( TrackGoAway(whichwindow, ZZ(thisevent->where))) {
  546.             HideWindow (whichwindow);
  547.         }
  548.         break;
  549.         case inzoomout:
  550.         case inzoomin:
  551.           if ( TrackBox(whichwindow, ZZ(thisevent->where), code)) {
  552.             ZoomWindow (whichwindow, code, 0);
  553.             GetPort (&saveport);
  554.             SetPort (whichwindow);
  555.             EraseRect (&swholescreen);
  556.             InvalRect (&swholescreen);
  557.             SetPort (saveport);
  558.         }
  559.         break;
  560.         case inContent:
  561.         
  562.         /* make the window active if it isn't yet */
  563.         if (whichwindow != FrontWindow()) {
  564.             SelectWindow(whichwindow);
  565.         }
  566.   
  567.         /* find our window data */
  568.         thewdatum = wdatum (whichwindow);
  569.         if (thewdatum) {
  570.           
  571.             /* convert the Point of click to the window's
  572.                own coordinates since this will be always
  573.                more useful than the global coordintates */
  574.             temp = thisevent->where;
  575.             SetPort (whichwindow);
  576.             GlobalToLocal (&temp);
  577.               x = temp.h;
  578.               y = temp.v;
  579.             
  580.             /* call the window's in content routine */
  581.             HLock (thewdatum);
  582.             (*((**thewdatum).wcontent))(x, y, whichwindow,
  583.                 thisevent);
  584.             HUnlock (thewdatum);
  585.         }
  586.         break;
  587.     }
  588. }
  589. /* Local procedure */
  590. /* Determine if MultiFinder is running by checking for the existence of the
  591.     WaitNextEvent() trap */
  592. static int
  593. MFIsRunning()
  594. {    /* $8F is for _MFDispatch, $9F is the unimplemented trap */
  595.     return (GetTrapAddress(0x8FL) != GetTrapAddress(0x9FL));
  596. }
  597.             
  598.  
  599. /************************************************************************/
  600. /*     GLOBAL ROUTINES INTENDED TO BE USER CALLABLE PROCEDURES        */
  601. /* THE FOLLOWING PROCEDURES HAVE BEEN WRITTEN FOR THE USER'S         */
  602. /* APPLICATION TO CALL.                            */
  603. /*                                     */
  604. /************************************************************************/
  605.  
  606. havenewrom ()            /* returns true if new roms installed    */
  607. {
  608.     return ((*((int *)ROM85)) == NEWROM);
  609. }
  610.  
  611. /* Menu is usually called like:
  612.  
  613.         menu ("File", "Print...", got_print)
  614.         
  615.    where the first argument is the name appearing on the menubar.  The
  616.    2nd argument is the name appearing when the menu is pulled down.  The
  617.    3rd argument is USUALLY the routine to be called when the user
  618.    selects this particular menu.  Non-existant menus are created following
  619.    the last.  The menu ordering may never be changed once created.
  620.    Existint menus have their "routine-to-be-executed" assignment changed
  621.    to the new routine.  If the long values 0L, 1L, 2L, or 3L are passed
  622.    instead of a procedure, the menu characteristic is set as specified
  623.    by the constants itemdisable, itemenable, itemcheck, itemuncheck.  For
  624.    example:
  625.            menu ("File", "Print...", itemdisable)
  626.         
  627.    PROCEDURES ASSIGNED TO MENUS ARE CALLED WITH TWO ARGUMENTS.  YOU
  628.    DO NOT NEED TO DECLARE THESE IN YOUR PROCEDURE IF YOU DO NOT USE
  629.    THEM.  FOR EXAMPLE, GOT_PRINT MAY BE DECLARED AS:
  630.    
  631.            got_print()
  632.         char *itemname;
  633.         EventRecord *current_event;
  634.         {
  635.             ...
  636.         }
  637.         
  638.    Itemname is a char* pointing to the Item name.  This allows the same
  639.    menu procedure to be used for multiple menu/Item pairs.  Maybe your
  640.    Size menu just as items 9 Point, 10 Point, 12 Point, etc.  This way
  641.    you can specify the same procedure for each and determine what to do
  642.    by looking at itemname.  
  643.    
  644.    Current_event is a pointer to the current EventRecord that detected
  645.    the menu selection.  You may look at this as needed.
  646. */
  647.    
  648. menu (name, Item, routine)        /* install or change a menu    */
  649. char *name;                /* the menu name         */
  650. char *Item;                /* the Item name         */
  651. ProcPtr routine;            /* a procedure or modifier     */
  652. {
  653.     menudatum **here,**temp;    /* a roving Handle to our data     */
  654.     menudatum **ourmhandle;        /* another Handle to our data     */
  655.     itemdatum **items,**tempitems;    /* a Handle to the Item     */
  656.     int lastid, lastitem;
  657.     
  658.     /* get the Handle to menu named 'name' */
  659.     if ((ourmhandle = getourmenuhandle (name)) == 0L) {
  660.     
  661.         /* make a new menu entry by finding the end of the list */
  662.         here = simplemenus;
  663.         HLock (here);
  664.         while ((**here).next) {
  665.             temp = here;
  666.             here = (menudatum **)(**here).next;
  667.             HUnlock (temp);
  668.             HLock (here);
  669.         }
  670.             
  671.         /* make a structure for our new entry */
  672.         lastid = (**here).menuId;
  673.         (**here).next = (Ptr)NewHandle ( (long)sizeof(menudatum));
  674.         temp = here;
  675.         here = (menudatum **)(**here).next;
  676.         HUnlock (temp);
  677.         HLock (here);
  678.  
  679.         strcpy ( (**here).menuname, name);
  680.         (**here).menuId = ++lastid;
  681.         (**here).next = (Ptr) 0L;
  682.         
  683.         /* make a new Item structure */
  684.         (**here).itemlist = (itemdatum **)NewHandle ( 
  685.             (long)sizeof(itemdatum));
  686.             
  687.         /* make a new menu entry for the Macintosh */
  688.         ctop (name);
  689.         (**here).menuhand = NewMenu (lastid, name);
  690.         ptoc (name);
  691.         items = (**here).itemlist;
  692.  
  693.         HLock (items);
  694.         strcpy ((**items).itemname, Item);
  695.         (**items).itemno = 1;
  696.         (**items).menuId = lastid;
  697.         (**items).menuhand = (**here).menuhand;
  698.         (**items).menurun = (ProcPtr) 0L;
  699.         (**items).next = 0L;
  700.         HUnlock (items);
  701.         
  702.         /* install and display the menu */
  703.         ctop (Item);
  704.         AppendMenu ((**here).menuhand, Item);
  705.         ptoc (Item);
  706.         InsertMenu ((**here).menuhand,0);
  707.         HUnlock (here);
  708.  
  709.         setitems (items, routine);
  710.         DrawMenuBar();
  711.         return(TRUE);
  712.     }
  713.     else {
  714.         HLock (ourmhandle);
  715.  
  716.         if (strlen(Item) == 0) {
  717.           /* then adjust main menu */
  718.           setitems( 0L - (long) ((**ourmhandle).menuhand), routine);
  719.           return(FALSE);
  720.         }
  721.  
  722.         /* see if Item is in list */
  723.         items = (**ourmhandle).itemlist;
  724.         HLock (items);
  725.  
  726.         while ( strcmp(Item,(**items).itemname) && (**items).next) {
  727.             tempitems = items;
  728.             items = (itemdatum **)(**items).next;
  729.             HUnlock (tempitems);
  730.             HLock (items);
  731.         }
  732.         if (strcmp(Item,(**items).itemname) ==0) {
  733.             setitems( items, routine);
  734.             return(FALSE);
  735.         }
  736.         else {
  737.             /* make new Item entry */
  738.             lastitem = (**items).itemno;
  739.             (**items).next =(Ptr)NewHandle((long)sizeof(itemdatum));
  740.             tempitems = items;
  741.             items = (itemdatum **)(**items).next;
  742.             HUnlock (tempitems);
  743.             HLock (items);
  744.  
  745.             strcpy ((**items).itemname, Item);
  746.             (**items).itemno = ++lastitem;
  747.             (**items).menuId = (**ourmhandle).menuId;
  748.             (**items).menuhand = (**ourmhandle).menuhand;
  749.             (**items).menurun = (ProcPtr) 0L;
  750.             (**items).next = 0L;
  751.             HUnlock (items);
  752.  
  753.             /* and install the Item in the menu bar */
  754.             ctop (Item);
  755.             AppendMenu ((**ourmhandle).menuhand,Item);
  756.             ptoc (Item);
  757.             HUnlock (ourmhandle);
  758.             setitems (items, routine);
  759.             return(TRUE);
  760.         }
  761.     }
  762. }
  763.  
  764. /* Given a menu name, return the real menu Handle as used by most
  765.    of the Macintosh toolbox menu manager routines.
  766. */
  767.  
  768. MenuHandle mhand (name)            /* find MenuHandle        */
  769. char *name;                /* given name of menu         */
  770. {
  771.     menudatum    **menu;    
  772.     MenuHandle    temp;        /* a Handle to our data     */
  773.  
  774.     menu = getourmenuhandle(name);
  775.     if ( menu ) {
  776.         HLock (menu);
  777.         temp = (**menu).menuhand;
  778.         HUnlock (menu);
  779.         return ( temp );    /* return menu Handle         */
  780.     } else
  781.         return ( (MenuHandle) 0 );    
  782. }
  783.  
  784.     
  785. /*  Call this routine if you want these SimpleTools defined quiting    */
  786. /*  procedures.  You may just install your own instead.     The time to    */
  787. /*  call this is after you have installed all your other "File" items.    */
  788. /*  By calling this last, you will place Transfer and Quit on the end    */
  789. /*  of the menu list.                            */
  790.  
  791. mac_toolquits ()
  792. {
  793.     menu ("File", "-", itemdisable);
  794.     menu ("File", "Transfer.../T", gottrans);
  795.     menu ("File", "Quit/Q", gotquit);
  796. }
  797.  
  798. /* Given a window's name, return its window pointer so that other
  799.    Macintosh Window Manager routines can be called for that window. */
  800.  
  801. WindowPtr windowpoint(name)        /* get window pointer         */
  802. char *name;                /* given window's name         */
  803. {
  804.     winddatum **wind, **tempwind;    /* Handle to our window data     */
  805.     WindowPtr    temp;
  806.  
  807.     if (firstwind) return ((WindowPtr)0); 
  808.     wind = simplewinds;        /* look for the named window     */
  809.     HLock (wind);
  810.  
  811.     while ( strcmp ((**wind).windname, name) && (**wind).next) {
  812.         tempwind = wind;
  813.         wind = (winddatum **) (**wind).next;
  814.         HUnlock (tempwind);
  815.         HLock (wind);
  816.     }
  817.     if ( strcmp ((**wind).windname, name) ==0) {
  818.         temp = (**wind).wptr;
  819.         HUnlock (wind);
  820.         return ( temp );    /* return pointer        */
  821.     } else {
  822.         HUnlock (wind);
  823.         return ( (WindowPtr) 0);/* or zero if it wasn't found    */
  824.     }
  825. }
  826.  
  827. /* This routine installs a new window onto the screen.  It also gives
  828.    that window an Item in the Window menu.  This routine is also used
  829.    to modify a window's associated routines.  The x,y positions are the
  830.    top left and bottom right corners of where the window should originally
  831.    be placed.  The coordinates are never used when this routine is called
  832.    to update an already existing window.  But the spaces must be filled,
  833.    so you can use zeros if you want.  Once the window has been displayed in
  834.    its original position, the user has complete control of its size and
  835.    placement with the mouse.
  836.    
  837.    YOU MUST ASSIGN PROCEDURES TO BE CALLED WHEN SIMPLETOOLS DETECTS THAT
  838.    THIS WINDOW IS BECOMMING ACTIVE, DEACTIVATING, NEEDS UPDATING, OR
  839.    THE MOUSE HAS BEEN PRESSED IN ITS CONTENT.  JUST LIKE THE MENU PROCEDURE,
  840.    THESE PROCEDURES ARE PASSED SOME ARGUMENTS.  YOU DO NOT HAVE TO 
  841.    DECLARE THESE IF YOU DON'T WHAT TO USE THEM.  IF YOU USE THE ARGUMENTS,
  842.    YOU WOULD DECLAR THESE PROCEDURES AS FOLLOWS:
  843.    
  844.        my_activate (windp, event)    same as my_update
  845.     my_deactivate (windp, event)    same as my_update
  846.     
  847.     my_update (windp, event)
  848.     WindowPtr     windp;        the window being acted upon
  849.     EventRecord     *event;        the current event record
  850.     {
  851.         ...
  852.     }
  853.     
  854.     my_inContent (x, y, windp, event)
  855.     int         x, y;        mouse position in local coords
  856.     WindowPtr     windp;        like above
  857.     EventRecord     *event;        like above
  858.     {
  859.         ...
  860.     }
  861. */
  862.  
  863. window(name, xtop, ytop, xbot, ybot, a, d, u, c)
  864. char *name;            /* window's name             */
  865. int xtop, ytop, xbot, ybot;    /* position if this is a new window     */
  866. ProcPtr a, d, u, c;        /* activate, deactivate, update, and     */
  867. {                /*  content procedures          */
  868.     winddatum **wind, **temp;/* Handle to our window data         */
  869.     winddatum **newentry;    /* another Handle             */
  870.     Rect newplace;        /* rectable for the window's placement    */
  871.  
  872.     if (a == (ProcPtr) 0)
  873.         a = stnop;
  874.     if (d == (ProcPtr) 0)
  875.         d = stnop;
  876.     if (u == (ProcPtr) 0)
  877.         u = stnop;
  878.     if (c == (ProcPtr) 0)
  879.         c = stnop;
  880.     if ( !firstwind ) {
  881.  
  882.         /* see if window is in the list */
  883.         wind = simplewinds;
  884.         HLock (wind);
  885.  
  886.         while ( strcmp ((**wind).windname, name) && (**wind).next) {
  887.             temp = wind;
  888.             wind = (winddatum **) (**wind).next;
  889.             HUnlock (temp);
  890.             HLock (wind);
  891.         }
  892.         if ( strcmp ((**wind).windname, name) ==0) {
  893.  
  894.             /* reset the found window's parameters */
  895.             (**wind).wact = (ProcPtr) a;
  896.             (**wind).wdeact = (ProcPtr) d;
  897.             (**wind).wupdate = (ProcPtr) u;
  898.             (**wind).wcontent = (ProcPtr) c;
  899.             SetPort ( (**wind).wptr);        
  900.             HUnlock (wind);
  901.  
  902.             return(FALSE);
  903.         }
  904.     }
  905.  
  906.     /* make a new window entry */
  907.     newentry = (winddatum **)NewHandle ( (long) sizeof (winddatum));
  908.     if (firstwind)
  909.         simplewinds = newentry;
  910.     else
  911.         (**wind).next = (Ptr) newentry;
  912.     firstwind = 0;
  913.     HUnlock (wind);
  914.     HLock (newentry);
  915.  
  916.     strcpy ((**newentry).windname, name);
  917.     SetRect (&newplace, xtop, ytop, xbot, ybot);
  918.     if (EmptyRect (&newplace)) 
  919.         SetRect (&newplace, 10, 42, 500, 330);
  920.     ctop (name);
  921.     (**newentry).wptr = NewWindow (0L, &newplace, name, -1, 
  922.         wprocid, -1L, dogoaway, newentry);
  923.     ptoc (name);
  924.     (**newentry).wact = (ProcPtr) a;
  925.     (**newentry).wdeact = (ProcPtr) d;
  926.     (**newentry).wupdate = (ProcPtr) u;
  927.     (**newentry).wcontent = (ProcPtr) c;
  928.     (**newentry).next = (Ptr) 0;
  929.     if (windmenu)
  930.         menu ("Windows", name, showawindow); 
  931.     SetPort ( (**newentry).wptr);        
  932.     HUnlock (newentry);
  933.  
  934.     return(TRUE);
  935. }
  936.  
  937. withwindow(name)            /* set output to window by name    */
  938. char *name;                /* give it the window's name     */
  939. {                    /* returns if window exists    */
  940.     winddatum **wind, **temp;
  941.     wind = simplewinds;
  942.     if (firstwind) return(FALSE);    /* search for the window's name */
  943.  
  944.     HLock (wind);
  945.     while ( strcmp ((**wind).windname, name) && (**wind).next) {
  946.         temp = wind;
  947.         wind = (winddatum **) (**wind).next;
  948.         HUnlock (temp);
  949.         HLock (wind);
  950.     }
  951.     if ( strcmp ((**wind).windname, name) ==0) {
  952.         SetPort ( (**wind).wptr);    /* set output to it     */
  953.         HUnlock (wind);
  954.         return(TRUE);
  955.     } else {
  956.         HUnlock (wind);
  957.         return(FALSE);
  958.     }
  959. }
  960.   
  961. /* This run procedure is used to install routines to be occasionally
  962.    run.  The routine will be run once for each call to simpleevents()
  963.    which is done repeatedly by runsimpletools().
  964.    
  965.    EACH ROUTINE INSERTED INTO THE RUN LIST IS RUN MULTIPLE TIMES UNTIL
  966.    IT IS REMOVED BY CALLING STOP.  THE ROUTINE IS CALLED WITH A SINGLE
  967.    ARGUMENT, A POINTER TO THE EVENT JUST RETURNED BY GETNEXTEVENT() AND
  968.    BEFORE SIMPLETOOLS PROCESSES IT.
  969. */
  970.  
  971. run(routine)            /* install a run procedure     */
  972. ProcPtr routine;        /* give it the procedure     */
  973. {                /* return TRUE if successful     */
  974.     int i;
  975.     i = 0;            /* add it to the end of the list */
  976.     while ( simpleruns[i] != (ProcPtr) 0L) i++;
  977.     if (i < maxsruns) {
  978.         simpleruns[i] = routine;
  979.         simpleruns[i+1] = (ProcPtr) 0L;
  980.         return(TRUE);
  981.     } else
  982.         return(FALSE);
  983. }
  984.  
  985. /* This routine removes a procedure from the list of run procedures */
  986.  
  987. stop(routine)            /* stop a procedure from running*/
  988. ProcPtr routine;        /* give the procedure         */
  989. {                /* return TRUE if successful     */
  990.     int i = 0;
  991.     while ( (simpleruns[i] != routine) && simpleruns[i])  i++;
  992.     if (simpleruns[i]) {
  993.         while ( simpleruns[i] != (ProcPtr)0 ) {
  994.             simpleruns[i] = simpleruns[i+1];
  995.             i++;
  996.         }
  997.         return(TRUE);
  998.     } else {
  999.         return(FALSE);
  1000.     }
  1001. }
  1002.  
  1003. home ()                /* text-based home of the pen with
  1004.                    the window being erased.        */
  1005. {
  1006.     GrafPtr    port;
  1007.     GetPort (&port);
  1008.     EraseRect (&(port->portRect));
  1009.     stgotoxy (1, 1);
  1010. }
  1011.  
  1012. stgotoxy (x, y)                /* goto text position x, y    */
  1013. int x, y;    
  1014. {
  1015.     Point        pt;
  1016.     int        newx, newy;
  1017.     FontInfo    font;
  1018.   
  1019.     GetFontInfo (&font);
  1020.     GetPen (&pt);
  1021.     if (x < 0) 
  1022.         newx = pt.h;
  1023.     else
  1024.         newx = font.widMax * (x);
  1025.     if (y < 0)
  1026.         newy = pt.v;
  1027.     else
  1028.         newy = (font.ascent + font.descent + font.leading) * (y+1);
  1029.     MoveTo (newx, newy);
  1030. }
  1031.  
  1032. /* The getline procedure is to be called when you want to simply get a Line
  1033.    of text from the user at the current pen position on the screen.  You
  1034.    will probably preceed this with a call to stgotoxy(x,y).  You would call
  1035.    it like:    
  1036.            getline ("Erik", name);
  1037.         
  1038.    where name is a character array.  This works MUCH better than scanf()
  1039.    or gets() since it uses the Macintosh TextEdit routines to allow the
  1040.    user to edit the Line being input.
  1041.    
  1042.    Getline is very "modal" and no other events are handled while the
  1043.    user is expected to enter the Line.  Getline returns ONLY when the
  1044.    user presses <RETURN>.  
  1045.    
  1046.    Routines scheduled to run by the run() routine are called.  Make sure
  1047.    your run routines don't strip all <RETURNS> from the event record
  1048.    they get or getline will never stop.
  1049. */
  1050.    
  1051. getline (dfault, destination)        /* using TE, get a Line        */
  1052. char *dfault, *destination;        /* default string, dest     */
  1053. {
  1054.     TEHandle         hte;
  1055.     Rect            destRect;
  1056.     Point            pen,pt;
  1057.     FontInfo        FInfo;
  1058.     int            done, mask, code, in_already, nextcap;
  1059.     GrafPtr            port, window;
  1060.     EventRecord        event;
  1061.     char            key;
  1062.     CursHandle        c;
  1063.     
  1064.     GetPort (&port);        /* Calculate Rect for TE    */
  1065.     if (port != FrontWindow())  SelectWindow (port);
  1066.     GetPen (&pen);
  1067.     GetFontInfo (&FInfo);
  1068.         SetRect (&destRect, pen.h, pen.v - FInfo.ascent,
  1069.             1000, pen.v + FInfo.descent);
  1070.     EraseRect (&destRect);
  1071.     hte = TENew (&destRect, &destRect);    
  1072.     TESetText (dfault, (long)strlen(dfault), hte);
  1073.     TEActivate (hte);
  1074.     TEUpdate (&destRect, hte);
  1075.     mask = mDownMask + keyDownMask + autoKeyMask + mUpMask;
  1076.     done = FALSE;
  1077.       c = GetCursor (iBeamCursor);
  1078.     in_already = FALSE;
  1079.     nextcap = getlinecaps;
  1080.     do {                /* "modal" loop until <cr>    */
  1081.         SystemTask ();
  1082.         TEIdle (hte);
  1083.         
  1084.         GetNextEvent (mask, &event);
  1085.         runruns (&event);
  1086.         GetMouse (&pt);        /* use I beam in TE        */
  1087.         if (PtInRect (ZZ(pt), &destRect)) {
  1088.           if ( ! in_already )  {
  1089.              SetCursor (*c);
  1090.              in_already = TRUE;
  1091.           }
  1092.         } else {
  1093.           if ( in_already ) {
  1094.               InitCursor ();
  1095.               in_already = FALSE;
  1096.           }
  1097.         }
  1098.         switch (event.what) {
  1099.             case mouseDown:
  1100.             code = FindWindow (ZZ(event.where),&window);
  1101.             if ((code == inContent) && (window == port)) {
  1102.                GlobalToLocal (&event.where);
  1103.                 if (PtInRect(ZZ(event.where),&destRect))
  1104.                     TEClick (ZZ(event.where), 0, hte);
  1105.                 else SysBeep (1);
  1106.             } else SysBeep (20);
  1107.             break;
  1108.             case keyDown:
  1109.             case autoKey:
  1110.                 key = (char) (event.message & 0xFFL);
  1111.             if (nextcap && (key >= 'a') && (key <= 'z')) 
  1112.                 key -= ' ';
  1113.             nextcap = FALSE;
  1114.             if (key == ' ') nextcap = getlinecaps;
  1115.             if (key != '\r')  TEKey (key, hte);
  1116.             else  done = TRUE;
  1117.             break;
  1118.         }
  1119.     } while (!done);
  1120.     TEDeactivate (hte);
  1121.     
  1122.     
  1123.     strncpy (destination, *TEGetText(hte), (*hte)->teLength);
  1124.     destination[(*hte)->teLength] = 0;
  1125.  
  1126.     TEDispose (hte);
  1127.         InitCursor ();
  1128. }
  1129.  
  1130. /*  Use prompt when you want a tiny window to pop up to ask the user
  1131.     a question.  The question is drawn and a TextEdit box is provided
  1132.     to get the answer.  Whatever the user leaves in the answer box
  1133.     is returned in answer.  Two buttons are also displayed:  OK and
  1134.     CANCEL.  Prompt returns TRUE or FALSE depending on which Button was
  1135.     pressed.
  1136. */
  1137.  
  1138. prompter ( question, answer)        /* dialog box question/answer */
  1139. char *question;
  1140. char *answer;
  1141. {
  1142.     return (stdialog (question, answer, 1));
  1143. }
  1144.  
  1145. /* Message is just like prompt except no answer box is displayed.  An
  1146.    OK and CANCEL Button works just like prompt.
  1147. */
  1148.  
  1149. message ( message )            /* dialog box message         */
  1150. char *message;
  1151. {
  1152.     return (stdialog (message, message, 2));
  1153. }
  1154.   
  1155. /*  This routine is a simpler whay to call the toolbox SFGetFile()
  1156.     routine.  Simple call this like:
  1157.     
  1158.             getfile ("TEXT", filename)
  1159.         
  1160.     where filename is a character array.  Replace TEXT with whatever
  1161.     file type you desire.  The file manager's working directory is set
  1162.     correctly so that a subsequent open() call with filename will work.
  1163. */
  1164.  
  1165. getfile (ftype, reply)
  1166. char ftype[];
  1167. char reply[];
  1168. {
  1169.     Point where;
  1170.     SFReply frommac;
  1171.     
  1172.       where.h = 75; where.v = 50;
  1173.     if (strlen(ftype) != 4)
  1174.       SFGetFile (ZZ(where), NULL, NULL, -1, NULL, NULL, &frommac);
  1175.     else
  1176.       SFGetFile (ZZ(where), NULL, NULL, 1, ftype, 0L, &frommac);
  1177.     if (frommac.good) {
  1178.       SetVol ("", frommac.vRefNum);
  1179.       strcpy (reply, frommac.fName);
  1180.       return (TRUE);
  1181.     }
  1182.     else return (FALSE);
  1183. }
  1184.  
  1185. /* This is like getfile, but may get a new file name from the user.
  1186.    Origname is the default you want to present to the user.
  1187. */
  1188.  
  1189. putfile (origname,reply)
  1190. char *origname;
  1191. SFReply *reply;
  1192. {
  1193.     Point where;
  1194.     SFReply frommac;
  1195.     
  1196.       where.h = 75; where.v = 50;
  1197.     SFPutFile (ZZ(where), "", origname, 0L, &frommac);
  1198.     if (frommac.good) {
  1199.       SetVol ("", frommac.vRefNum);
  1200.       strcpy (reply, frommac.fName);
  1201.       return (TRUE);
  1202.     }
  1203.     return (FALSE);
  1204. }
  1205.  
  1206. /* This routine initializes SimpleTools and MUST be called before    */
  1207. /* most of the other SimpleTools routines are called.            */
  1208. /* The passed about string is the menu Item name to appear just under    */
  1209. /* the Apple menu.  This will be disabled and can be enabled using    */
  1210. /* a menu() call.  This routine also initializes the Macintosh         */
  1211. /* for application execution and desk accessory processing.        */
  1212.  
  1213. mac_tools(about)    /* to be called at the beginning of program     */
  1214. char *about;
  1215. {
  1216.     InitGraf (&thePort);    /* initialize the screen         */
  1217.     InitFonts();        
  1218.     InitWindows();
  1219.     InitMenus();
  1220.     TEInit();
  1221.     InitDialogs(0L);
  1222.     InitCursor();        /* make the arrow Cursor         */
  1223.     FlushEvents (everyEvent,0);  /* ignore left over events     */
  1224.     snewrom = havenewrom();
  1225.     
  1226.     wprocid = documentProc;
  1227.     if (snewrom) wprocid = zoomproc;
  1228.     SetRect ( &sizerect, 20, 50, 250, 330);
  1229.     simpleruns[0] = (ProcPtr) 0;  /* empty the run list         */
  1230.  
  1231.     /* These are the bounds we are allowed to size a window or
  1232.        Move a window to.  
  1233.     */
  1234.  
  1235.     swholescreen = dragrect = thePort -> portRect;
  1236.     InsetRect (&dragrect, 4, 4);
  1237.     SetRect ( &sizerect, 20, 20, 2048, 700);
  1238.     firstwind = 1;            /* empty window table        */
  1239.     keydownproc = stnop;        /* default key hit procedures     */
  1240.     autokeyproc = stnop;
  1241.     initsmenus(about);        /* install the menus         */
  1242.     if(MFIsRunning())
  1243.         MFenable = 1;        /* Set if MF is on        */
  1244. }
  1245.  
  1246. mac_toolsevents()            /* to be called in the main loop */
  1247. {
  1248.     EventRecord newevent;
  1249.     winddatum **thewdatum;
  1250.     int c = -1;
  1251.     long menuEquiv;
  1252.     
  1253.     HiliteMenu(0);
  1254.     if(MFenable)
  1255.         WaitNextEvent(everyEvent, &newevent, MFticks, 0L);
  1256.     else {
  1257.         SystemTask();        /* Do the system D.A. etc. stuff */
  1258.         GetNextEvent(everyEvent, &newevent);
  1259.     }
  1260.     
  1261.     runruns(&newevent);        /* Do our run procedures     */
  1262.     switch (newevent.what) {
  1263.         case mouseDown:
  1264.         if (StdEvent(&newevent))/* Check for stdio only events    */
  1265.         {
  1266.             return(c);      /* Exit if stdio - he's done it */
  1267.         }
  1268.         domousedown(&newevent); break;
  1269.         case keyDown:
  1270.         if ((newevent.modifiers & cmdKey) &&
  1271.              (menuEquiv = MenuKey((char)(newevent.message & 0xffL)))){
  1272.                 docommand(menuEquiv);
  1273.                 break;
  1274.         }
  1275.         c = newevent.message & charCodeMask;
  1276.         if ((newevent.modifiers & cmdKey) && /* Map control chars */
  1277.             (sysenvn->keyBoardType < 4)) /* on non-adb keyboards */
  1278.                 c &= 0x1f;    /* make it cntl */
  1279.         (*(keydownproc))(&newevent);
  1280.          break;
  1281.         case autoKey:
  1282.         if ((newevent.modifiers & cmdKey) &&
  1283.              (menuEquiv = MenuKey((char)(newevent.message & 0xffL)))){
  1284.                 docommand(menuEquiv);
  1285.                 break;
  1286.         }
  1287.         c = newevent.message & charCodeMask;
  1288.         if ((newevent.modifiers & cmdKey) && /* Map control chars */
  1289.             (sysenvn->keyBoardType < 4)) /* on non-adb keyboards */
  1290.                 c &= 0x1f;    /* make it cntl */
  1291.         (*(autokeyproc))(&newevent);
  1292.         break;
  1293.         case activateEvt: 
  1294.         if (StdEvent(&newevent))/* Check for stdio only events    */
  1295.         {
  1296.             return(c);      /* Exit if stdio - he's done it */
  1297.         }
  1298.         thewdatum = wdatum(newevent.message);
  1299.         if (thewdatum) {
  1300.             SetPort(newevent.message);
  1301.             HLock (thewdatum);
  1302.             if (newevent.modifiers & 1) {
  1303.  
  1304.                 (*((**thewdatum).wact))(newevent.message, 
  1305.                     &newevent);
  1306.             } else {
  1307.                 (*((**thewdatum).wdeact))(newevent.message,
  1308.                     &newevent);
  1309.             }
  1310.             HUnlock (thewdatum);
  1311.         }
  1312.         break;
  1313.         case updateEvt:
  1314.         if (StdEvent(&newevent))/* Check for stdio only events    */
  1315.         {
  1316.             return(c);      /* Exit if stdio - he's done it */
  1317.         }
  1318.         thewdatum = wdatum(newevent.message);
  1319.         if (thewdatum) {
  1320.             SetPort (newevent.message);
  1321.             BeginUpdate (newevent.message);
  1322.             HLock (thewdatum);
  1323.             (*((**thewdatum).wupdate))(newevent.message,
  1324.                 &newevent);
  1325.             HUnlock (thewdatum);
  1326.             EndUpdate (newevent.message);
  1327.         }
  1328.         break;
  1329.         case app4Evt:
  1330.             if(newevent.message & 0x01)
  1331.                 MFticks = 0;    /* Resume event */
  1332.             else
  1333.                 MFticks = 0;    /* Suspend event */
  1334.             break;
  1335.         case networkEvt:
  1336.         case driverEvt:
  1337.             mac_netevt(newevent.message);
  1338.             break;
  1339.         default: 
  1340.         if (StdEvent(&newevent))/* Check for stdio only events    */
  1341.         {
  1342.             return(c);      /* Exit if stdio - he's done it */
  1343.         }
  1344.         break;
  1345.     }
  1346.     return(c);
  1347. }
  1348.  
  1349. runsimpletools ()
  1350. {
  1351.     for (;;) mac_toolsevents();
  1352. }
  1353.